package com.alibaba.shardingtest.config;
import java.util.Properties;

import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory;
import org.apache.shardingsphere.infra.config.mode.ModeConfiguration;
import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
import org.apache.shardingsphere.mode.repository.standalone.StandalonePersistRepositoryConfiguration;
import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableReferenceRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.audit.ShardingAuditStrategyConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.keygen.KeyGenerateStrategyConfiguration;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;

@Configuration
public class ShardingConfig implements InitializingBean {



    @Autowired
    private ShardingProperties shardingProperties;


    public DataSource ShardingDataSource() throws SQLException, IOException {
        return ShardingSphereDataSourceFactory.createDataSource(getModeConfig(),getDataSourceMap(),getRuleConfigList(),new Properties());
    }


    private ModeConfiguration getModeConfig(){
        return new ModeConfiguration("Standalone", new StandalonePersistRepositoryConfiguration("JDBC", new Properties()));
    }

    private Collection<RuleConfiguration> getRuleConfigList(){
        Collection<RuleConfiguration> ruleConfigurationList = new ArrayList<>();
        ruleConfigurationList.add(createShardingRuleConfig());
        return ruleConfigurationList;
    }

    private Map<String, DataSource> getDataSourceMap(){
        Map<String, DataSource> dataSourceMap = new HashMap<>();
        for (String dataSourceName : shardingProperties.getDataSources().keySet()){
            DataSource dataSource = shardingProperties.getDataSources().get(dataSourceName);
            dataSourceMap.put(dataSourceName,dataSource);
        }
        return dataSourceMap;
    }

    public ShardingRuleConfiguration createShardingRuleConfig(){
        ShardingRuleConfiguration result = new ShardingRuleConfiguration();
        result.getTables().add(getOrderTableRuleConfiguration());
        result.getTables().add(getOrderItemTableRuleConfiguration());
        result.getBindingTableGroups().add(new ShardingTableReferenceRuleConfiguration("order","t_order,t_order_item"));
        return result;
    }

    private ShardingTableRuleConfiguration getOrderTableRuleConfiguration() {
        ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_order", "demo_ds_${0..1}.t_order_${[0, 1]}");
        result.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("order_id", "snowflake"));
        result.setAuditStrategy(new ShardingAuditStrategyConfiguration(Collections.singleton("sharding_key_required_auditor"), true));
        return result;
    }

    private ShardingTableRuleConfiguration getOrderItemTableRuleConfiguration() {
        ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_order_item", "demo_ds_${0..1}.t_order_item_${[0, 1]}");
        result.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("order_item_id", "snowflake"));
        return result;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        ShardingDataSource();
    }
}
